package com.allinfinance.starters.loader;

import com.allinfinance.starters.exception.LoadResourceException;
import com.allinfinance.starters.interfaces.StringConfigLoader;
import com.allinfinance.starters.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @desc: 文件类型配置加载器实现
 * @author: wujp
 * @create: 2025-01-13 17:05
 */
public class FileConfigLoader implements StringConfigLoader {
    private Logger logger = LoggerFactory.getLogger(FileConfigLoader.class);

    private Resource[] localFileResources;

    private String suffix;

    private String fileEncoding;

    private String note;//注释字符

    @Override
    public Map<String, String> load() {
        Map<String, String> configMap = new ConcurrentHashMap<>();
        logger.info("FileConfigLoader load config start.");
        try {
            for (Resource resource : localFileResources) {
                loadAllFiles(resource.getFile(), configMap);
            }
        } catch (Exception e) {
            throw new LoadResourceException("FileConfigFlowModelLoader load config resource error", e);
        }
        logger.info("FileConfigLoader load config end. config size is {}", configMap.size());
        return configMap;
    }

    private void loadAllFiles(File file, Map<String, String> configMap) throws IOException {
        BasicFileAttributes basicFileAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
        if (basicFileAttributes.isDirectory()) {
            File[] subFiles = file.listFiles();
            for (File subFile : subFiles) {
                loadAllFiles(subFile, configMap);
            }
        } else if (basicFileAttributes.isRegularFile() && file.getName().endsWith(suffix)) {
            String key = file.getName().substring(0, file.getName().lastIndexOf(suffix));
            if (configMap.containsKey(key)) {
                throw new LoadResourceException(String.format("file=%s has same file name.", file.getName()));
            }
            configMap.put(key, FileUtil.readFile(file, fileEncoding, note));
        } else {
            logger.warn("this file not match load config skip load . file={}", file.getAbsoluteFile());
        }
    }

    @Override
    public int getOrder() {
        return 100;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.localFileResources, "localFileResources must be set value");
        Assert.notNull(this.suffix, "suffix must be set value");
        Assert.notNull(this.fileEncoding, "fileEncoding must be set value");
        Assert.notNull(this.note, "note must be set value");
    }

    public Resource[] getLocalFileResources() {
        return localFileResources;
    }

    public void setLocalFileResources(Resource[] localFileResources) {
        this.localFileResources = localFileResources;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public String getFileEncoding() {
        return fileEncoding;
    }

    public void setFileEncoding(String fileEncoding) {
        this.fileEncoding = fileEncoding;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
}
